package com.dld.hll.financial;

import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;

import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Hello world!
 */
public class App {
    Gson gson = new Gson();

    public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {


        long sourceTenantID = 1293L;
        long targetTenantID = 1032L;

        String profile = System.getProperty("financial.profiles.active");
        String url = "jdbc:mysql://172.20.223.249:3306/db_financial_task?useUnicode=true&allowMultiQueries=true&serverTimezone=GMT%2B8";
        String user = "task@usr";
        String pwd = "task#pwd";

        if (StringUtils.equals(profile, "slave")) {
            url = "jdbc:mysql://mysql.financial.slave.hualala.com:3308/db_financial_task?useUnicode=true&allowMultiQueries=true&serverTimezone=GMT%2B8";
            user = "extractor";
            pwd = "extractor";
        }

        String s = System.getProperty("sourceTenantID");
        if (StringUtils.isNotEmpty(s)) {
            sourceTenantID = Long.valueOf(s);
        }
        String t = System.getProperty("targetTenantID");
        if (StringUtils.isNotEmpty(t)) {
            targetTenantID = Long.valueOf(t);
        }

        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection conn = DriverManager.getConnection(url, user, pwd);

        Map<String, Map<String, Column>> map = new HashMap<>();
        List<Data> dataList = getData(targetTenantID);
        for (Data data : dataList) {
            Map<String, Column> columnMap = new HashMap<>();

            PreparedStatement ps = conn.prepareStatement("SELECT column_name, data_type FROM `information_schema`.`COLUMNS` WHERE table_schema = ? and table_name = ? ");
            ps.setString(1, data.getDatabaseName());
            ps.setString(2, data.getTableName());
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                String columnName = rs.getString(1);
                String dataType = rs.getString(2);
                Column column = new Column();
                column.setColumnName(columnName);
                column.setDataType(dataType);
                columnMap.put(columnName, column);

            }
            map.put(data.getTableName(), columnMap);

        }

        for (Data data : dataList) {
            String tableName = data.getTableName();
            Map<String, Column> columnMap = map.get(tableName);
            List<String> columnList = columnMap.values().stream().map(Column::getColumnName).collect(Collectors.toList());
            StringBuilder sb = new StringBuilder();
            sb.append("select ");
            for (String columnName : columnList) {
                sb.append(columnName).append(",");
            }
            String sql = sb.substring(0, sb.length() - 1);
            sql += " from " + data.getDatabaseName() + "." + data.getTableName() + data.getCondition();

            System.out.println(sql);
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setLong(1, sourceTenantID);
            ResultSet rs = ps.executeQuery();
            FileWriter fw = new FileWriter(tableName);
            fw.append(data.getInit());

            while (rs.next()) {
                fw.append("insert into ").append(tableName).append("(");
                for (int i = 0; i < columnList.size(); i++) {
                    if (i == columnList.size() - 1) {
                        fw.append(columnList.get(i)).append(")");
                    } else {
                        fw.append(columnList.get(i)).append(",");
                    }
                }
                fw.append("values (");

                for (int i = 0; i < columnList.size(); i++) {
                    String columnName = columnList.get(i);
                    String dataType = columnMap.get(columnName).getDataType();
                    String val = getValue(dataType, columnName, rs);
                    if (columnName.equalsIgnoreCase("tenantID") || columnName.equalsIgnoreCase("groupID")) {
                        val = String.valueOf(targetTenantID);
                    }
                    if (i == columnList.size() - 1) {
                        fw.append("\"").append(val).append("\"").append(");").append(System.lineSeparator());
                    } else {
                        fw.append("'").append(val).append("'").append(",");
                    }
                }
            }
            fw.close();
        }
        conn.close();
    }

    private static String getValue(String dataType, String columnName, ResultSet rs) throws SQLException {
        if (dataType.equals("bigint")) {
            return String.valueOf(rs.getLong(columnName));
        }
        if (dataType.equals("tinyint")) {
            return String.valueOf(rs.getByte(columnName));
        }
        if (dataType.equals("decimal")) {
            return rs.getBigDecimal(columnName).toString();
        }
        if (dataType.equals("json")) {
            String json = rs.getString(columnName);
            return json.replace("\"", "\\\"");
        }

        return rs.getString(columnName);
    }

    public static List<Data> getData(Long targetTenantID) {

        Data data = new Data();
        data.setDatabaseName("db_hr_base");
        data.setTableName("tbl_hr_emp_group");
        data.setCondition(" where tenantID = ? ");
        data.setInit("use db_hr_base;" + System.lineSeparator() + "delete from tbl_hr_emp_group where tenantID = " + targetTenantID + ";" + System.lineSeparator());

        Data data1 = new Data();
        data1.setDatabaseName("db_hr_base");
        data1.setTableName("tbl_hr_emp_group_detail");
        data1.setCondition(" where tenantID = ? ");
        data1.setInit("use db_hr_base;" + System.lineSeparator() + "delete from tbl_hr_emp_group_detail where tenantID = " + targetTenantID + ";" + System.lineSeparator());

        Data data2 = new Data();
        data2.setDatabaseName("db_hr_base");
        data2.setTableName("tbl_hr_tenant_org");
        data2.setCondition(" where groupID = ? ");
        data2.setInit("use db_hr_base;" + System.lineSeparator() + "delete from tbl_hr_tenant_org where groupID = " + targetTenantID + ";" + System.lineSeparator());

        Data data3 = new Data();
        data3.setDatabaseName("db_hr_base");
        data3.setTableName("tbl_hr_employee");
        data3.setCondition(" where groupID = ? ");
        data3.setInit("use db_hr_base;" + System.lineSeparator() + "delete from tbl_hr_employee where groupID = " + targetTenantID + ";" + System.lineSeparator());

        Data data4 = new Data();
        data4.setDatabaseName("db_hr_base");
        data4.setTableName("tbl_hr_auditor_type");
        data4.setCondition(" where tenantID = ? ");
        data4.setInit("use db_hr_base; " + System.lineSeparator() + "delete from tbl_hr_auditor_type where tenantID = " + targetTenantID + ";" + System.lineSeparator());

        Data data5 = new Data();
        data5.setDatabaseName("db_financial_bpm");
        data5.setTableName("tbl_bpm_flow_detail");
        data5.setCondition("  where flowID = 630102703768293377 and 1 != ? ");
        data5.setInit("use db_financial_bpm;" + System.lineSeparator() + "delete from tbl_bpm_flow_detail where flowID = 630102703768293377;" + System.lineSeparator());
//
        Data data6 = new Data();
        data6.setDatabaseName("db_financial_bpm");
        data6.setTableName("tbl_bpm_form_service");
        data6.setCondition(" where formID = 630102703768293378 and  tenantID = ? ");
        data6.setInit("use db_financial_bpm;" + System.lineSeparator() + "delete from tbl_bpm_form_service where formID = 630102703768293378;" + System.lineSeparator());

        Data data7 = new Data();
        data7.setDatabaseName("db_financial_bpm");
        data7.setTableName("tbl_bpm_busi_type");
        data7.setCondition(" where tenantID = ? ");
        data7.setInit("use db_financial_bpm;" + System.lineSeparator() + "delete from tbl_bpm_busi_type where tenantID = " + targetTenantID + ";" + System.lineSeparator());
        Data data8 = new Data();
        data8.setDatabaseName("db_financial_bpm");
        data8.setTableName("tbl_bpm_flow_instance");
        data8.setCondition(" where instanceID = 630102703768293376 and  tenantID = ? ");
        data8.setInit("use db_financial_bpm; " + System.lineSeparator() + "delete from tbl_bpm_flow_instance where tenantID = " + targetTenantID + ";" + System.lineSeparator());
        Data data9 = new Data();
        data9.setDatabaseName("db_financial_bpm");
        data9.setTableName("tbl_bpm_flow_master");
        data9.setCondition(" where flowID = 630102703768293377 and  tenantID = ? ");
        data9.setInit("use db_financial_bpm; " + System.lineSeparator() + "delete from tbl_bpm_flow_master where tenantID = " + targetTenantID + ";" + System.lineSeparator());
        Data data10 = new Data();
        data10.setDatabaseName("db_financial_bpm");
        data10.setTableName("tbl_bpm_form");
        data10.setCondition(" where formID = 630102703768293378 and tenantID = ? ");
        data10.setInit("use db_financial_bpm; " + System.lineSeparator() + "delete from tbl_bpm_form where tenantID = " + targetTenantID + ";" + System.lineSeparator());



        return Arrays.asList(data, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10);
    }
}
